home *** CD-ROM | disk | FTP | other *** search
- program glenz1;
- {
- Glenz vector #1
- - by Bjarke Viksφe
- aug 1994
-
- On a 320x200x16 colour screen.
- No tweaking here, my friend. The vector routine is pretty much the
- same as allways, though.
- But instead of writing colours to all bitplanes, I simply fill out
- one bitplane at a time and set up the palette to look like it's
- all transparent!
- }
-
- {{$DEFINE DEBUG}
-
- uses
- DEMOINIT;
-
- const
- WIDTH = 40;
- NUMBER_FACES = 24;
- NUMBER_COORDS = 14;
- BOX = 115; {size of box}
- BOXA = 60;
-
- type
- facetype = RECORD
- l1,l2,l3,l4 : byte;
- shown,up : boolean;
- end;
-
- var
- slope : array[0..200*2] of integer;
- face : array[1..NUMBER_FACES] of facetype;
- cbuffer : array[0..NUMBER_COORDS*2-1] of integer;
-
- miny,maxy : integer;
- scrminy,scrmaxy : integer;
- lastscrminy, lastscrmaxy : integer;
-
- sinustabel : array[0..639] of integer;
- v1,v2,v3 : word;
- cos1,sin1,cos2,sin2,cos3,sin3 : integer;
-
- LineTable1 : array[0..319] of byte;
- LineTable2 : array[0..319] of byte;
-
-
- const
- display1 : word = $0000;
- display2 : word = $4000;
- coords : array[0..NUMBER_COORDS*3-1] of integer =
- (box,box,-box, -box,box,-box, -box,-box,-box, box,-box,-box,
- box,box,box, -box,box,box, -box,-box,box, box,-box,box,
- 0,box+boxa,0, 0,-box-boxa,0, box+boxa,0,0, -box-boxa,0,0,
- 0,0,box+BOXA, 0,0,-box-boxa);
-
-
- (*------------------------------------------------*)
-
- procedure SetupSinus;
- var
- i : integer;
- v, vadd : real;
- begin
- v:=0.0;
- vadd:=(2.0*pi/512.0);
- for i:=0 to 639 do begin
- sinustabel[i]:=round(sin(v)*32767);
- v:=v+vadd;
- end;
- end;
-
- procedure SetupCoords;
- begin
- with face[1] do begin l1:=1; l2:=0; l3:=13; up:=FALSE; end;
- with face[2] do begin l1:=2; l2:=1; l3:=13; up:=TRUE; end;
- with face[3] do begin l1:=3; l2:=2; l3:=13; up:=FALSE; end;
- with face[4] do begin l1:=0; l2:=3; l3:=13; up:=TRUE; end;
-
- with face[5] do begin l1:=4; l2:=5; l3:=12; up:=FALSE; end;
- with face[6] do begin l1:=5; l2:=6; l3:=12; up:=TRUE; end;
- with face[7] do begin l1:=6; l2:=7; l3:=12; up:=FALSE; end;
- with face[8] do begin l1:=7; l2:=4; l3:=12; up:=TRUE; end;
-
- with face[9] do begin l1:=0; l2:=1; l3:=8; up:=TRUE; end;
- with face[10] do begin l1:=1; l2:=5; l3:=8; up:=FALSE; end;
- with face[11] do begin l1:=5; l2:=4; l3:=8; up:=TRUE; end;
- with face[12] do begin l1:=4; l2:=0; l3:=8; up:=FALSE; end;
-
- with face[13] do begin l1:=2; l2:=3; l3:=9; up:=TRUE; end;
- with face[14] do begin l1:=3; l2:=7; l3:=9; up:=FALSE; end;
- with face[15] do begin l1:=7; l2:=6; l3:=9; up:=TRUE; end;
- with face[16] do begin l1:=6; l2:=2; l3:=9; up:=FALSE; end;
-
- with face[17] do begin l1:=1; l2:=2; l3:=11; up:=FALSE; end;
- with face[18] do begin l1:=2; l2:=6; l3:=11; up:=TRUE; end;
- with face[19] do begin l1:=6; l2:=5; l3:=11; up:=FALSE; end;
- with face[20] do begin l1:=5; l2:=1; l3:=11; up:=TRUE; end;
-
- with face[21] do begin l1:=3; l2:=0; l3:=10; up:=FALSE; end;
- with face[22] do begin l1:=0; l2:=4; l3:=10; up:=TRUE; end;
- with face[23] do begin l1:=4; l2:=7; l3:=10; up:=FALSE; end;
- with face[24] do begin l1:=7; l2:=3; l3:=10; up:=TRUE; end;
- end;
-
- procedure InitDemo;
- var
- i : integer;
- begin
- Screen_Off;
- ClearWholeScreen;
- SetupSinus;
- SetupCoords;
-
- scrminy := 0; scrmaxy := 200;
- lastscrminy := 0; lastscrmaxy := 200;
- v1:=0; v2:=0; v3:=0;
-
- for i:=0 to 319 do begin
- LineTable1[i]:=2 SHL ((7-i) AND 7)-1;
- LineTable2[i]:=(255 SHL ((7-i) AND 7));
- end;
- for i:=0 to 200 do ytabel[i]:=i*WIDTH;
-
- SetRGB(0,0,0,0);
- SetRGB(1,60,15,15); {001} {all xx1 bits are darkred faces}
- SetRGB(2,60,24,24); {010} {all x1x bits are lightred faces}
- SetRGB(3,60,24,24); {011}
- SetRGB(4,63,63,63); {100} {all 1xx bits are white faces}
- SetRGB(5,60,60,60); {101}
- SetRGB(6,63,63,63); {110}
- SetRGB(7,63,63,63); {111}
-
- Screen_On;
- end;
-
-
- (*------------------------------------------------*)
-
- procedure SwapDisplay;
- var
- temp : word;
- begin
- temp:=display2;
- display2:=display1;
- display1:=temp;
- SetAddress(Ptr(SEGA000,display2));
- end;
-
- procedure ClearScreen(y1,y2 : integer); assembler;
- {Yes, clear the screen... or the part of it we use!}
- asm
- mov es,SEGA000
- mov di,display1
- add di,(WIDTH*15)+8
- xor ax,ax
- mov dx,170 {height}
- cld
- @loop:
- mov cx,(192/8)/2 {width}
- rep stosw
- add di,(320-192)/8
- dec dx
- jnz @loop
- end;
-
-
- (*------------------------------------------------*)
-
- procedure ClearSlope; assembler;
- asm
- mov ax,ds
- mov es,ax
- lea di,slope
- DB LONG; mov ax,$8000; DW $8000;
- cld
- mov cx,200
- rep; DB LONG; stosw
- end;
-
- procedure CalcSlope(l1,l2 : integer); assembler;
- {Calc edgebuffer for face}
- var
- ysize : integer;
- asm
- lea si,cbuffer
- DB LONG; xor cx,cx
- mov bx,l1
- shl bx,2
- mov ax,[si+bx]
- mov cx,[si+bx+2]
- mov bx,l2
- shl bx,2
- add si,bx
- mov dx,[si]
- mov bx,[si+2]
-
- cmp bx,cx
- jle @noswap
- xchg ax,dx
- xchg bx,cx
- @noswap:
- cmp bx,miny
- jae @miny
- mov miny,bx
- @miny:
- cmp cx,maxy
- jbe @maxy
- mov maxy,cx
- @maxy:
-
- sub cx,bx
- jcxz @zero
- mov ysize,cx
- add bx,bx
- add bx,bx
- lea si,slope
- add si,bx
-
- mov bx,dx {hide it in BX}
- sub ax,dx
- inc ax
-
- DB LONG; shl ax,16
- {cdq} DB $66,$99
- DB LONG; idiv cx
- DB LONG; mov dx,ax
- DB LONG; shr dx,16
-
- @one:
-
- mov cx,bx {retrive hidden DX}
- xor bx,bx
- mov di,$8000
- push bp
- mov bp,ysize
- @loop:
- cmp [si],di {is first slot occupied? use other then...}
- jne @other
- mov [si],cx
- add bx,ax
- adc cx,dx
- add si,4
- dec bp
- jnz @loop
- jmp NEAR PTR @done
- @other:
- mov [si+2],cx
- add bx,ax
- adc cx,dx
- add si,4
- dec bp
- jnz @loop
- @done:
- pop bp
- @zero:
- end;
-
-
- (*------------------------------------------------*)
-
- procedure CalcAngle;
- begin
- sin1:=sinustabel[v1]; cos1:=sinustabel[v1+128];
- sin2:=sinustabel[v2]; cos2:=sinustabel[v2+128];
- sin3:=sinustabel[v3]; cos3:=sinustabel[v3+128];
- v1:=(v1-2) AND 511;
- v2:=(v2-1) AND 511;
- v3:=(v3+1) AND 511;
- end;
-
- procedure RotateAllCoords;
- var
- i, a,b : integer;
- x,y,z : longint;
- temp : integer;
- begin
- a:=0; b:=0;
- for i:=1 to NUMBER_COORDS do begin
- x:=coords[a]; y:=coords[a+1]; z:=coords[a+2];
- inc(a,3);
-
- temp:=y;
- y:=(LongMul(y,cos1) - LongMul(z,sin1)) DIV 32768;
- z:=(LongMul(temp,sin1) + LongMul(z,cos1)) DIV 32768;
- temp:=x;
- x:=(LongMul(x,cos2) + LongMul(z,sin2)) DIV 32768;
- z:=(LongMul(z,cos2) - LongMul(temp,sin2)) DIV 32768;
- temp:=x;
- x:=(LongMul(x,cos3) - LongMul(y,sin3)) DIV 32768;
- y:=(LongMul(temp,sin3) + LongMul(y,cos3)) DIV 32768;
-
- cbuffer[b]:=((x SHL 8) DIV (z+800))+160;
- cbuffer[b+1]:=((y SHL 8) DIV (z+800))+100;
- inc(b,2);
- end;
- end;
-
-
- function FaceShown(i : integer; l1,l2,l3 : byte) : boolean;
- {Is face turning the back on us? Then don't show it.
- Formula is: (x1-x2)*(y3-y2) - (x1-x2)*(y3-y2) > 0}
- var
- a,b : longint;
- begin
- a := LongMul(cbuffer[l1]-cbuffer[l2],cbuffer[l3+1]-cbuffer[l2+1]);
- b := LongMul(cbuffer[l1+1]-cbuffer[l2+1],cbuffer[l3]-cbuffer[l2]);
- face[i].shown:=(a-b) > 0;
- end;
-
-
- procedure FillShape(y,ysize : integer; color : byte); assembler;
- asm
- cmp ysize,200
- jae @done
- mov ax,y
- add ax,ax
- mov si,ax
- mov di,[si+OFFSET ytabel]
- add di,display1 {find vga address offset}
- lea si,slope {find where edgebuffer begins}
- add ax,ax
- add si,ax
-
- mov es,SEGA000
- mov dx,$3CE {prepare set bitplanes}
- mov al,$08
- out dx,al
- cld
- @yloop:
- lodsw
- mov dx,ax
- lodsw
- cmp ax,dx
- jle @exchange
- xchg ax,dx
- @exchange:
-
- cmp dx,0
- jl @filledout_fast
- cmp ax,320
- jge @filledout_fast
- cmp ax,0
- jge @cut1
- xor ax,ax
- @cut1:
- cmp dx,319
- jle @cut2
- mov dx,319
- @cut2:
- push si
- push di
- mov bx,ax
- mov si,dx
- mov dx,$3CF
-
- mov al,[bx+OFFSET LineTable1]
- mov ah,[si+OFFSET LineTable2]
- shr bx,3
- shr si,3
- mov cx,si
- sub cx,bx
- jcxz @1
-
- dec cx
- add di,bx
- mov bh,ah
- out dx,al
- mov bl,color
- mov al,[es:di]
- mov [es:di],bl
- inc di
- jcxz @4
- mov al,$FF
- out dx,al
-
- mov al,bl
- mov ah,al
- shr cx,1
- rep stosw
- adc cx,0
- rep stosb
-
- @4:
- mov al,bh
- out dx,al
- mov al,[es:di]
- mov [es:di],bl
- jmp NEAR PTR @filledout
-
- @1:
- add di,bx
- mov bl,color
- and al,ah
- out dx,al
- mov al,[es:di]
- mov [es:di],bl
-
-
- @filledout:
- pop di
- pop si
- @filledout_fast:
- add di,WIDTH
- dec ysize
- jnz @yloop
- @done:
- end;
-
-
- procedure RunOnce;
- var
- i : integer;
- begin
- SwapDisplay;
- VBLANK;
- {$IFDEF DEBUG}
- SetRGB(0,20,0,0);
- {$ENDIF}
-
- SetWriteMode(2);
- SetBitMaskRegister($FF);
- SetBitplanes(15);
- ClearScreen(lastscrminy,lastscrmaxy);
-
- lastscrminy := scrminy; lastscrmaxy := scrmaxy;
- scrminy := 200; scrmaxy := 0;
-
- CalcAngle;
- RotateAllCoords;
-
- {calc which faces are front/behind...}
- for i:=1 to NUMBER_FACES do with face[i] do
- FaceShown(i, l1 SHL 1,l2 SHL 1,l3 SHL 1);
-
- {draw one of the "back" bitplanes}
- for i:=1 to NUMBER_FACES do if (NOT face[i].shown) AND (face[i].up) then begin
- with face[i] do begin
- SetBitplanes(1); {Write to bitplane 1 only}
- ClearSlope;
- miny := 200; maxy := 0;
- CalcSlope(l1,l2);
- CalcSlope(l2,l3);
- CalcSlope(l3,l1);
- FillShape(miny, maxy-miny, 1);
- if (miny < scrminy) then scrminy := miny;
- if (maxy > scrmaxy) then scrmaxy := maxy;
- end;
- end;
-
- {draw the other of the "back" bitplanes}
- for i:=1 to NUMBER_FACES do if (NOT face[i].shown) AND (NOT face[i].up) then begin
- with face[i] do begin
- SetBitplanes(2); {write to bitplane 2 only}
- ClearSlope;
- miny := 200; maxy := 0;
- CalcSlope(l1,l2);
- CalcSlope(l2,l3);
- CalcSlope(l3,l1);
- FillShape(miny, maxy-miny, 2);
- if (miny < scrminy) then scrminy := miny;
- if (maxy > scrmaxy) then scrmaxy := maxy;
- end;
- end;
-
- {draw white top faces}
- for i:=1 to NUMBER_FACES do if face[i].shown AND face[i].up then begin
- with face[i] do begin
- SetBitplanes(4); {write to bitplane 3 only}
- ClearSlope;
- miny := 200; maxy := 0;
- CalcSlope(l1,l2);
- CalcSlope(l2,l3);
- CalcSlope(l3,l1);
- FillShape(miny, maxy-miny, 4);
- if (miny < scrminy) then scrminy := miny;
- if (maxy > scrmaxy) then scrmaxy := maxy;
- end;
- end;
-
- {$IFDEF DEBUG}
- SetRGB(0,0,0,0);
- while KeyHit[26] do ;
- {$ENDIF}
- end;
-
-
- begin
- SetScreenMode($D);
- InitDemo;
- SetAllInterrupts;
- repeat RunOnce until Key='e';
- RestoreAllInterrupts;
- SetScreenMode(TEXTMODE);
- end.
-